package loginservice

import (
	"errors"
	"go-middle/app/common/model/admin"
	"go-middle/app/common/model/admin_online"
	"go-middle/library/ip"
	"go-middle/library/token"
	"strings"
	"time"

	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gcache"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gvalid"
	"github.com/mssola/user_agent"
)

const (
	//AdminNoPass 用户
	AdminNoPass string = "admin_no_pass_"
	//AdminLock 锁定用户
	AdminLock string = "admin_lock_"
	//AdminInfo session存储用户
	AdminInfo string = "admin_info_"
	//CaptchaKey 图形验证码KEY
	CaptchaKey string = "captcha"
)

//ReqLoginAccount 登录请求结构体
type ReqLoginAccount struct {
	UserName string `p:"username" v:"required#请输入账号" `
	Password string `p:"password" v:"required|length:6,30#请输入密码|密码长度为:min到:max位"`
	Captcha  string `p:"captcha" v:"required#请输入图形验证码"`
}

//SignIn 用户登录，成功返回用户信息，否则返回nil; passport应当会md5值字符串
func SignIn(loginName, password string) (user *admin.Entity, e error) {
	//查询用户信息
	err := gvalid.Check(loginName, "phone", nil)
	var where string
	if err != nil {
		where = "user=?"
	} else {
		where = "mobile=?"
	}
	user, e = admin.Model.Where(where, loginName).Where("delete_time=0").FindOne()
	if e != nil {
		glog.Error(e)
	}
	if user == nil {
		e = errors.New("用户不正确")
		return
	}
	if user.State == 1 {
		e = errors.New("账号已禁用")
		return
	}
	//校验密码
	if !strings.EqualFold(user.Password, gmd5.MustEncryptString(gconv.String(user.CreateTime)+password+user.Salt)) {
		e = errors.New("密码错误")
		return
	}
	return
}

//SetPasswordCounts 记录密码尝试次数
func SetPasswordCounts(user string) string {
	if CheckLock(user) {
		return "账号已锁定"
	}
	curTimes := 0
	curTimeObj := gcache.Get(AdminNoPass + user)
	if curTimeObj != nil {
		curTimes = gconv.Int(curTimeObj)
	}
	curTimes++
	gcache.Set(AdminNoPass+user, curTimes, time.Minute*30)
	if curTimes >= 5 {
		Lock(user)
		return "账号已锁定"
	}
	return ",还有" + gconv.String(5-curTimes) + "次之后账号将锁定"
}

//SetOnLine 设置在线状态
func SetOnLine(r *ghttp.Request) {
	//保存在线状态
	userAgent := r.Header.Get("User-Agent")
	ua := user_agent.New(userAgent)
	os := ua.OS()
	browser, _ := ua.Browser()
	loginIp := r.GetClientIp()
	loginLocation := ip.GetAddressByIp(loginIp)
	var userOnline *admin_online.Entity
	userOnline, _ = admin_online.Model.
		FindOne("admin_id=? and driver_type=?", r.Session.GetInt64("uid"), ip.GetDriverType(userAgent))
	if userOnline == nil {
		userOnline = new(admin_online.Entity)
	}
	if userOnline.Token != "" {
		//删除旧token相关信息
		_ = token.SessionStore.RemoveAll(userOnline.Token)
	}
	userOnline.DriverType = ip.GetDriverType(userAgent)
	userOnline.AdminId = r.Session.GetInt64("uid")
	userOnline.Token = r.Session.Id()
	userOnline.Browser = browser
	userOnline.Os = os
	userOnline.LoginIp = loginIp
	userOnline.CreateTime = gtime.Now().Unix()
	userOnline.UpdateTime = gtime.Now().Unix()
	userOnline.Status = "on"
	userOnline.LoginLocation = loginLocation
	_, _ = userOnline.Save()
}

//RemovePasswordCounts 移除密码错误次数
func RemovePasswordCounts(user string) {
	gcache.Remove(AdminNoPass + user)
}

//Lock 锁定账号
func Lock(user string) {
	gcache.Set(AdminLock+user, true, 30*time.Minute)
}

//Unlock 解除锁定
func Unlock(user string) {
	gcache.Remove(AdminLock + user)
}

//CheckLock 检查账号是否锁定
func CheckLock(user string) bool {
	result := false
	rs := gcache.Get(AdminLock + user)
	if rs != nil {
		result = true
	}
	return result
}
